﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.UI;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	public class LayGroundStorehouseNozzle
	{
		public LayGroundStorehouseNozzle(ExternalCommandData comd, LayBasementSprinklerParameter lay)
		{
			this.layParameter = lay;
			this.commandData = comd;
			this.doc = comd.Application.ActiveUIDocument.Document;
		}

		public IList<BeamData> GetBeamData(IList<CurveLoop> curveLoops)
		{
			List<BeamData> list = new List<BeamData>();
			if (curveLoops == null)
			{
				return null;
			}
			double viewProjectElevation = this.GetViewProjectElevation(this.doc.ActiveView);
			double levelToUpLevelHeight = this.GetLevelToUpLevelHeight(this.doc, viewProjectElevation);
			foreach (CurveLoop arCurveLoop in curveLoops)
			{
				List<BeamData> elementByCurveLoop = LayGroundStorehouseNozzle.GetElementByCurveLoop(this.doc, null, arCurveLoop, levelToUpLevelHeight);
				if (elementByCurveLoop.Count > 0)
				{
					list.AddRange(elementByCurveLoop);
				}
			}
			foreach (LinkedDocument linkedDocument in this.doc.GetLinkedDocuments())
			{
				Transform transform = Transform.CreateTranslation(linkedDocument.Transform.Origin * -1.0);
				foreach (CurveLoop curveLoop in curveLoops)
				{
					List<Curve> list2 = new List<Curve>();
					CurveLoopIterator curveLoopIterator = CurveLoop.CreateViaCopy(curveLoop).GetCurveLoopIterator();
					while (curveLoopIterator.MoveNext())
					{
						Curve curve = curveLoopIterator.Current;
						curve = curve.CreateTransformed(transform);
						list2.Add(curve);
					}
					if (list2.Count > 0)
					{
						CurveLoop arCurveLoop2 = CurveLoop.Create(list2);
						list.AddRange(LayGroundStorehouseNozzle.GetElementByCurveLoop(linkedDocument.Document, linkedDocument.Transform, arCurveLoop2, levelToUpLevelHeight));
					}
				}
			}
			return list;
		}

		public bool Run(IList<CurveLoop> curveLoops, List<XYZ> lstPoint, List<BeamData> beamLst)
		{
			bool result;
			try
			{
				if (curveLoops == null)
				{
					result = false;
				}
				else
				{
					double viewProjectElevation = this.GetViewProjectElevation(this.doc.ActiveView);
					this.GetLevelToUpLevelHeight(this.doc, viewProjectElevation);
					if (!this.GetLayRect(beamLst))
					{
						result = false;
					}
					else
					{
						RectLayParamers rectParater = this.GetRectParater();
						rectParater.XSpace = 3000.0;
						rectParater.YSpace = 3000.0;
						if (rectParater == null)
						{
							result = false;
						}
						else
						{
							RectLayPoint rectLayPoint = new RectLayPoint(rectParater);
							if (rectLayPoint.Points == null || rectLayPoint.Points.Count < 1)
							{
								this.szError = "没有合适的布置点，可能主梁所围成矩形区域过小!";
								result = false;
							}
							else
							{
								this.listPoints = lstPoint;
								this.startMin = rectParater.PointBase;
								this.startMax = rectLayPoint.PointEnd;
								this.startEnd = rectParater.PointDiagonal;
								result = true;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				if (ex.ToString().Contains("您取消了操作！"))
				{
					throw new OperationCanceledException("您取消了操作！", ex);
				}
				string message = ex.Message;
				result = false;
			}
			return result;
		}

		public RectLayParamers GetRectParater()
		{
			return new RectLayParamers
			{
				LayType = 1,
				BeiShu = 50,
				XSpace = 3400.0,
				YSpace = 3400.0,
				XMargin = 1700.0,
				YMargin = 1700.0,
				LessDistance = 2400.0,
				AngleRow = 0.0,
				PointBase = this.beamManage.maxRect.Min(),
				PointDiagonal = this.beamManage.maxRect.Max()
			};
		}

		public bool GetLayRect(List<BeamData> elemsSle)
		{
			List<BeamData> allPrimaryBeam = this.GetAllPrimaryBeam(elemsSle);
			if (allPrimaryBeam == null || allPrimaryBeam.Count < 1)
			{
				this.szError = "没有找到主梁";
			}
			this.beamManage.Init();
			this.beamManage.AddElements(allPrimaryBeam);
			return this.beamManage.Cal(ref this.szError);
		}

		public List<BeamData> GetAllPrimaryBeam(List<BeamData> arEle)
		{
			List<BeamData> list = new List<BeamData>();
			foreach (BeamData beamData in arEle)
			{
				FamilyInstance familyInstance = beamData.Entbaem as FamilyInstance;
				if (familyInstance != null && this.IsPrimaryBeam(familyInstance))
				{
					list.Add(beamData);
				}
			}
			return list;
		}

		public bool IsPrimaryBeam(FamilyInstance famIns)
		{
			bool result = false;
			if (famIns.Category.Id.IntegerValue != -2001320)
			{
				return result;
			}
			if (this.GetBeamOrderType(famIns) == BeamOrderType.BT_PrimaryBeam)
			{
				result = true;
			}
			return result;
		}

		private Outline GetOutLine(XYZ dPoint)
		{
			double num = 1.0;
			XYZ xyz = new XYZ(dPoint.X - num / 2.0, dPoint.Y - num / 2.0, dPoint.Z - num / 2.0);
			XYZ xyz2 = new XYZ(dPoint.X + num / 2.0, dPoint.Y + num / 2.0, dPoint.Z + num / 2.0);
			return new Outline(xyz, xyz2);
		}

		public List<ElementId> GetJoineElements(FamilyInstance famIns)
		{
			List<ElementId> result = new List<ElementId>();
			Document document = famIns.Document;
			Curve curve = (famIns.Location as LocationCurve).Curve;
			if (curve == null || curve.Tessellate().Count < 2)
			{
				return result;
			}
			XYZ endPoint = curve.GetEndPoint(0);
			XYZ endPoint2 = curve.GetEndPoint(1);
			ElementFilter elementFilter = new BoundingBoxIntersectsFilter(this.GetOutLine(endPoint));
			BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(this.GetOutLine(endPoint2));
			LogicalOrFilter logicalOrFilter = new LogicalOrFilter(elementFilter, boundingBoxIntersectsFilter);
			return new FilteredElementCollector(document).WherePasses(logicalOrFilter).ToElementIds().ToList<ElementId>();
		}

		public BeamOrderType GetBeamOrderType(FamilyInstance famIns)
		{
			BeamOrderType result = BeamOrderType.BT_SecondaryBeam;
			Document document = famIns.Document;
			IEnumerable<ElementId> joineElements = this.GetJoineElements(famIns);
			ElementId levelId = famIns.GetParameter(BuiltInParameter.INSTANCE_REFERENCE_LEVEL_PARAM).AsElementId();
			int num = 0;
			foreach (ElementId elementId in joineElements)
			{
				Element element = document.GetElement(elementId);
				if (element != null && (this.IsColumnWithSameLevel(element, levelId) || this.IsShearWallWithSameLevel(element, levelId)))
				{
					num++;
				}
				if (2 == num)
				{
					result = BeamOrderType.BT_PrimaryBeam;
					break;
				}
			}
			return result;
		}

		private bool IsColumnWithSameLevel(Element ele, ElementId levelId)
		{
			bool result = false;
			if (!(ele is FamilyInstance))
			{
				return false;
			}
			if (ele.Category.Id.IntegerValue == -2000100 || ele.Category.Id.IntegerValue == -2001330)
			{
				result = true;
			}
			return result;
		}

		private bool IsShearWallWithSameLevel(Element ele, ElementId levelId)
		{
			bool result = false;
			if (ele is Wall)
			{
				Wall elem = ele as Wall;
				int num = elem.GetParameter(BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT).AsInteger();
				elem.GetParameter(BuiltInParameter.WALL_HEIGHT_TYPE).AsElementId();
				if (1 == num)
				{
					result = true;
				}
			}
			return result;
		}

		private static List<BeamData> GetElementByCurveLoop(Autodesk.Revit.DB.Document docCur, Transform tf, CurveLoop arCurveLoop, double extrusionDist)
		{
			List<BeamData> list = new List<BeamData>();
			if (arCurveLoop == null)
			{
				return list;
			}
			Solid solid = null;
			try
			{
				solid = GeometryCreationUtilities.CreateExtrusionGeometry(new List<CurveLoop>
				{
					arCurveLoop
				}, XYZ.BasisZ, extrusionDist);
			}
			catch (Exception)
			{
			}
			new ElementCategoryFilter((Autodesk.Revit.DB.BuiltInCategory)(-1999010));
			ElementFilter elementFilter = new ElementCategoryFilter(BuiltInCategory.OST_StructuralFraming);
			ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(Wall));
			ElementIntersectsSolidFilter elementIntersectsSolidFilter = new ElementIntersectsSolidFilter(solid);
			LogicalAndFilter logicalAndFilter = new LogicalAndFilter(new LogicalOrFilter(elementFilter, elementClassFilter), elementIntersectsSolidFilter);
			foreach (Element element in new FilteredElementCollector(docCur).WherePasses(logicalAndFilter).ToElements().ToList<Element>())
			{
				if (element is FamilyInstance || element is Wall)
				{
					list.Add(new BeamData(element, tf));
				}
			}
			return list;
		}

		public double GetViewProjectElevation(Autodesk.Revit.DB.View view)
		{
			double result = 0.0;
			Level genLevel = view.GenLevel;
			if (genLevel == null)
			{
				return result;
			}
			return genLevel.ProjectElevation;
		}

		public double GetLevelToUpLevelHeight(Autodesk.Revit.DB.Document doc, double dElevation)
		{
			Level upLevelByElevation = LayGroundStorehouseNozzle.GetUpLevelByElevation(doc, dElevation);
			double result;
			if (upLevelByElevation != null)
			{
				result = upLevelByElevation.Elevation - dElevation;
			}
			else
			{
				result = 26.246719160104988;
			}
			return result;
		}

		public static Level GetUpLevelByElevation(Autodesk.Revit.DB.Document doc, double dElevation)
		{
			Level result = null;
			List<Level> list = new FilteredElementCollector(doc).OfClass(typeof(Level)).Cast<Level>().ToList<Level>();
			SortedDictionary<double, Level> sortedDictionary = new SortedDictionary<double, Level>();
			foreach (Level level in list)
			{
				if (level.Elevation > dElevation)
				{
					double key = Math.Abs(level.Elevation - dElevation);
					if (!sortedDictionary.ContainsKey(key))
					{
						sortedDictionary.Add(key, level);
					}
				}
			}
			if (sortedDictionary.Count > 0)
			{
				result = sortedDictionary.First<KeyValuePair<double, Level>>().Value;
			}
			return result;
		}

		public IList<Space> CreatSpaceByViewRoom(Autodesk.Revit.DB.Document doc)
		{
			IList<Space> list = new List<Space>();
			foreach (Element element in ((IEnumerable<Element>)YJKElementFilter.GetElementByCategory(doc, BuiltInCategory.OST_Rooms)))
			{
				Room room = element as Room;
				if (room != null)
				{
					list.Add(YJKRevitTools.CreatSpace(doc, room));
				}
			}
			return list;
		}

		public IList<Space> CreateSpaceByLinkDoc(UIApplication uiApp)
		{
			IList<Space> list = new List<Space>();
			Transaction transaction = new Transaction(uiApp.ActiveUIDocument.Document, "C");
			transaction.Start();
			try
			{
				string value = "";
				Dictionary<Room, Transform> linkAllRoom = this.GetLinkAllRoom(uiApp, ref value);
				string.IsNullOrEmpty(value);
				if (linkAllRoom != null)
				{
					IList<Level> list2 = new List<Level>();
					foreach (KeyValuePair<Room, Transform> keyValuePair in linkAllRoom)
					{
						if (keyValuePair.Key != null && keyValuePair.Key.Name.Contains("车库"))
						{
							Space space = YJKRevitTools.CreatSpace(this.doc, keyValuePair.Key, keyValuePair.Value, ref list2);
							if (space != null)
							{
								list.Add(space);
							}
						}
					}
				}
				transaction.Commit();
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
			return list;
		}

		public Dictionary<Room, Transform> GetLinkAllRoom(UIApplication uiApp, ref string linkName)
		{
			Dictionary<Room, Transform> dictionary = new Dictionary<Room, Transform>();
			Document document = uiApp.ActiveUIDocument.Document;
			FilteredElementCollector elementsOfType = YJKElementFilter.GetElementsOfType(document, typeof(Instance), BuiltInCategory.OST_RvtLinks);
			IList<string> linkFilePaths = YJKRevitTools.GetLinkFilePaths(document);
			foreach (Element element in elementsOfType)
			{
				Instance instance = element as Instance;
				if (instance != null)
				{
					Transform totalTransform = instance.GetTotalTransform();
					(document.GetElement(instance.GetTypeId()) as RevitLinkType).GetParameter(BuiltInParameter.WALL_ATTR_ROOM_BOUNDING).Set(1);
					string value = instance.Name.Substring(0, instance.Name.IndexOf(".rvt"));
					string text = "";
					foreach (string text2 in linkFilePaths)
					{
						if (text2.Contains(value))
						{
							text = text2;
						}
					}
					if (File.Exists(text))
					{
						FilteredElementCollector filteredElementCollector = new FilteredElementCollector(uiApp.Application.OpenDocumentFile(text));
						filteredElementCollector.OfCategory(BuiltInCategory.OST_Rooms);
						new List<double>();
						new List<double>();
						IEnumerator<Element> enumerator3 = filteredElementCollector.GetEnumerator();
						{
							while (enumerator3.MoveNext())
							{
								Element element2 = enumerator3.Current;
								Room room = element2 as Room;
								if (room.Location != null)
								{
									dictionary.Add(room, totalTransform);
								}
							}
							continue;
						}
					}
					int length = instance.Name.IndexOf(":");
					linkName = linkName + instance.Name.Substring(0, length) + "\n";
				}
			}
			return dictionary;
		}

		public LayBasementSprinklerParameter layParameter;

		private ExternalCommandData commandData;

		private Document doc;

		public BeamDataManage beamManage = new BeamDataManage();

		public List<XYZ> listPoints;

		public XYZ startMin;

		public XYZ startMax;

		public XYZ startEnd;

		public string szError = "";
	}
}
